
//  接口数据
let retrievalData,timeout,isLink=false,targetNode=null,sourceNode=null,lastSize=10,noOperate=false;
window.addEventListener('message',function(e){
  let data = e.data
  retrievalData = data.data
  // console.log(JSON.parse(data));
  layui.use(['layer','table','element','form','tree','treeSelect','notice','colorpicker','GraphVisFilter','admin','laypage'], function () {
    var $ = layui.jquery;
    var layer = layui.layer;
    var element = layui.element;
    var form = layui.form;
    var tree = layui.tree;
    var treeSelect = layui.treeSelect;
    var notice = layui.notice;
    var table = layui.table;
    var colorpicker = layui.colorpicker;
    var admin = layui.admin;
    var laypage = layui.laypage;
    var GraphVisFilter = layui.GraphVisFilter;

    var router = layui.router();
    var params=router.search;
    let parentNode = []
    let dataObj = {}
    let treeNodes = {}
    let VueThis = null

	//定义全局图数据缓存，用于本地实现扩展
	var graphDataCache=null;

	//执行界面事件
	bindDefaultEevent();
  // 绘制节点树状图
  // initNodeTree()
  initVue()
	//节点右键菜单
	const NodeRightMenu = {
		init : function(_graphvis){
			var self = this;
			if($("#nodeContextMenu").length == 0){
				$("#visual-panel").append(nodeRightMenuTempl.innerHTML);
				$("#visual-panel").on('click','#nodeContextMenu .menu-btn',function(){
          var type = $(this).attr('attrType');
          if(type == 'nodeDetail'){
            showNodeInfo(_graphvis.currentNode);
            // console.log(_graphvis.currentNode);
          }else if(type == 'nodeConfig'){
            openNodeConfig(_graphvis.currentNode);
          }else if(type=='expanded'){
            if(!_graphvis.currentNode.expendFlag){
              dbClickNodeEvent(_graphvis.currentNode);
            }
					}else if(type=='contract'){
						if(_graphvis.currentNode.expendFlag){
							dbClickNodeEvent(_graphvis.currentNode);
						}
					}else if(type == 'deleteNode'){
            //  需要调用一下删除的接口
            deleteNode(_graphvis,type)
            // _graphvis.rightMenuOprate(type);
          }else if(type == 'addNode'){
            // 新增数据
            addNode(_graphvis.currentNode)
          }else if(type == 'updateNode'){
            updateNode(_graphvis.currentNode)
          }else if(type == 'nodeConnent'){
            _graphvis.rightMenuOprate(type);
            sourceNode = _graphvis.currentNode
            isLink = true
          }else if(type == 'lookEvent'){
            //
            showNodeEvent(_graphvis.currentNode);
          }
          else{
						_graphvis.rightMenuOprate(type);
					}
				    self.hide();
				});
			}
		},
		show : function(e,_graphvis){
			this.init(_graphvis);
			$("#nodeContextMenu").css({top:e.pageY-30,left:e.pageX+10}).show();
		},
		hide : function(){
			$("#nodeContextMenu").hide();
		}
	};

	// 连线右键菜单
	const LinkRightMenu = {
		init : function(_graphvis){
			var self = this;
			if($("#linkContextMenu").length == 0){
				$("#visual-panel").append(linkRightMenuTempl.innerHTML);
				$("#visual-panel").on('click','#linkContextMenu .menu-btn',function(){
				    var type = $(this).attr('attrType');
				    if(type == 'lineConfig'){
					    openLinkConfig(_graphvis.currentLink);
				    }else if(type == 'delEdge'){
              beforeDelLink(_graphvis,type)
            }else{
					    _graphvis.rightMenuOprate(type);
				    }
				    self.hide();
				});
			}
		},
		show : function(e,_graphvis){
			this.init(_graphvis);
			$("#linkContextMenu").css({top:e.pageY-30,left:e.pageX+10}).show();
		},
		hide : function(){
			$("#linkContextMenu").hide();
		}
	};

	// 空白区域右键菜单
	const spaceAreaRightMenu = {
		init : function(_graphvis){
			var self = this;
			if($("#spaceAreaContextMenu").length == 0){
				$("#visual-panel").append(spaceAreaRightMenuTempl.innerHTML);
				$("#visual-panel").on('click','#spaceAreaContextMenu .menu-btn',function(){
				    var type = $(this).attr('attrType');
				    if(type == 'savePng'){
						visgraph.saveImage(5000,5000,'png');
					}else if(type == 'saveJPEG'){
						visgraph.saveImage(5000,5000,'jpeg');
					}else if(type == 'mouseNormal'){
						visgraph.setMouseModel('normal');
					}else if(type == 'mouseSelect'){
						visgraph.setMouseModel('select');
					}else if(type == 'export'){
						visgraph.exportJsonFile();
					}
				    self.hide();
				});
			}
		},
		show : function(e,_graphvis){
			this.init(_graphvis);
			$("#spaceAreaContextMenu").css({top:e.pageY-30,left:e.pageX+10}).show();
		},
		hide : function(){
			$("#spaceAreaContextMenu").hide();
		}
	};

	//图可视化动态扩展插件
	let visActivePlugin = null;
	//可视化默认配置
	const config = {
		node:{ //节点的默认配置
			label:{ //标签配置
				show: true, //是否显示
				color: 'black', //字体颜色
				font: 'normal 16px KaiTi', //字体大小及类型
				textOffsetY:2, //纵向位移
				textPosition: 'Bottom_Center' //文字位置 Middle_Center,Bottom_Center
			},
      name:{
        show: true, //是否显示
				color: 'black', //字体颜色
				font: 'normal 16px KaiTi', //字体大小及类型
				textOffsetY:2, //纵向位移
				textPosition: 'Bottom_Center' //文字位置 Middle_Center,Bottom_Center
      },
			shape:'circle',//节点形状类型
			size:60, //节点大小
			color:'30,160,255',//节点颜色
			borderColor: '230,230,230', //边框颜色
			borderWidth: 0, //边框宽度,
			lineDash: [0], //边框虚线间隔,borderWidth>0时生效
			alpha: 1, //节点透明度
			selected: { //选中时的样式设置
				borderColor: '20,240,20', //选中时边框颜色
				borderAlpha: 0.8, //选中时的边框透明度
				borderWidth: 2, //选中是的边框宽度
				showShadow: true, //是否展示阴影
				shadowColor: '20,250,20', //选中是的阴影颜色
				shadowBlur:30 //阴影大小
			},
			onClick: function(event, node) {
        $("#link-panel").hide();
        // resetNodeInfo(node);//显示节点信息
        visgraph.showAllLink()
        if(isLink){
          targetNode = node
          isLink = false
          addLink()
        }
        // clearTimeout(timeout);
        // timeout = setTimeout(()=>{
        //   visgraph.highLightNeiberNodes(node,0.2)	//相邻节点高亮显示，其他节点设置为指定透明度
        //   clearTimeout(timeout);
        // },300)
			},
			onMousedrag:function(event,node){
				node.dragging=true;//记录拖拽事件
				node.dragStartPoint = {x:node.x,y:node.y};
			},
			ondblClick:function(event,node){
        event.cancelBubble = true
				dbClickNodeEvent(node);//双击展开及收缩
        // clearTimeout(timeout);
			},
			onMouseUp: function (event, node) {
				visActivePlugin.dragNodeEnd(node);//增加拖拽结束事件
			}
		},
		link: { //连线的默认配置
			label: { //连线标签
				show: true, //是否显示
				color: 'black', //字体颜色
				font: 'normal 12px KaiTi', //字体大小及类型Arial
				background:'240,240,240'
			},
			lineType: 'direct', //连线类型,curver,vlink,hlink,vbezier,hbezier
			colorType: 'defined', //连线颜色类型 source:继承source颜色,target:继承target颜色 both:用双边颜色，d:自定义
			color: 'black', //连线颜色
			alpha: 1, // 连线透明度
			lineWidth: 1.5, //连线宽度
			lineDash: [0], //虚线间隔样式如：[15,3,3,3]
			showArrow: true,//显示连线箭头
			arrowType:'triangle',//箭头形状 arrow,triangle
			selected: { //选中时的样式设置
				color: '120,250,110', //选中时的颜色
				alpha: 1,
				showShadow: false, //是否展示阴影
				shadowColor:'20,250,50' //选中连线时的阴影颜色
			},
			onClick: function(event, link) {
				//连线信息设置
				$('#link-source').text(link.source.label);
				$('#link-target').text(link.target.label);
				$('#link-label').text(link.label);
				//连线提示层定位
				$("#link-panel").css({
					top: event.pageY + 5,
					left:event.pageX - 165
				}).show();
			}
		},
		rightMenu:{
		  nodeMenu:NodeRightMenu,
		  linkMenu:LinkRightMenu
		},
		highLightNeiber:true,
		wheelZoom:0.8,
		noElementClick: function(event,_graphvis) { //空白区域点击
			if(event.button == 2){
				spaceAreaRightMenu.show(event,_graphvis);
			}else{
				spaceAreaRightMenu.hide();
			}
			$("#link-panel").hide();
		}
	};

	//1、初始化图对象
	let visgraph = new VisGraph(document.getElementById('graph-panel'),config);
	visgraph.switchAnimate(true);//开启绘制动画

	//2、初始化节点扩展插件的部分
	visActivePlugin = new GraphVisActivePlugin(visgraph,{
      layoutWorker:"libs/layoutWorker.js", //异步布局算法的库文件路径
			nodeRadius:30, //节点半径大小
			minCircleRadius:120//扩展区域最小半径
		});

	//3、模拟从服务器接口查询数据后绘制数据，可批量绘图，也可作为缓存本地扩展
	// var _data = loadRemoteData('data/hongloumeng.json');
	// graphDataCache = loadRemoteData('data/hongloumeng.json');

	//4、批量绘制可视化图数据
	visgraph.drawData(retrievalData);
	visgraph.setZoom();//设置自适应窗口大小
  setTimeout(()=>{
    runLayout('fastFR',{'froce':0.95,'linkDistance':150,'linkStrength':0.09,'charge':-300,gravity:0.015},true);
  })


	//实体点的详细信息面板
	function showNodeInfo(node){
		layer.closeAll('page');
		admin.popupRight({
		    id: 'nodeinfo-1',
        title:'节点信息',
		    type:1,
		    shade:0,
        area:['400px','100%'],
		    content:$('#nodeInfoTeml').html(),
		    success:function(layero,index){
          getDetail(node.properties)
          resetNodeInfo(node);
		    }
		});
	};

	//重置节点详细信息
	function resetNodeInfo(node){
		$('#nodeLabel').val(node.label);
		$('#nodeId').val(node.id);

		//输出关系节点
		var outNodes = (node.outLinks||[]).map((link) =>{
			return {
				id:link.target.id,
				label:link.target.label,
				type:link.target.type,
				color:'rgb('+link.target.fillColor+')',
				relationType:link.type||link.label||'--'
			};
		});

		//输入关系节点
		var inNodes = (node.inLinks||[]).map((link) =>{
			return {
				id:link.source.id,
				label:link.source.label,
				type:link.source.type,
				color:'rgb('+link.target.fillColor+')',
				relationType:link.type||link.label||'--'
			};
		});

		$('#relate-targetnum').text(outNodes.length);
		$('#relate-sourcenum').text(inNodes.length);
		var tableHeader=[[{title:'实体对象',field:'label',templet:function(d){return '<a href="javascript:;" lay-event="findNode" style="color:'+d.color+';"><span class="layui-badge-dot" style="background:'+d.color+';"></span> '+d.label+'</a>'}},{title:'关系类型',field:'relationType',width:150}]];
		createTable('outRelationTable',tableHeader,outNodes,false);
		createTable('inRelationTable',tableHeader,inNodes,false);

		table.on('tool(relationTable)', function(obj){
			var node = obj.data;
			var layEvent = obj.event;
			if(layEvent === 'findNode'){
				visgraph.findNodeById(node.id);
			}
		});
    //  获取它的详细信息的页面
    let props = []
    if(items.length){
      items.forEach(item => {
        if(!item.hidden){
          props.push({
            propName:item.header,
            propValue:item.value
          })
        }
      })
      tableHeader=[[{title:'属性名',field:'propName',width:150},{title:'属性值',field:'propValue',templet:function(d){
        return "<div id='prop"+d.LAY_INDEX+"' title='"+d.propValue+"'>" + d.propValue + "</div>"
      }}]];
      createTable('nodePropTable',tableHeader,props,false,100);
    }
	};
  //  重置节点事件信息
  function resetNodeEventInfo(node,result,init){
    $('#nodeEvLabel').val(node.label);
    tableHeader=[[{title:'序号',field:'No'},{title:'舷号',field:'shipNumber'},{title:'国别',field:'country',width:80},{title:'时间',field:'time'},{title:'描述',field:'description',templet:function(d){
      return "<div id='prop"+d.LAY_INDEX+"' title='"+d.description+"'>" + d.description + "</div>"
    }},{title:'来源',field:'source'},{title:'备注',field:'remark'}]];
    createTable('nodeEventTable',tableHeader,result.data,false,lastSize);
    if(init){
      creatPage('eventpage',result.total,lastSize)
    }
  }
  //新增线条关系
  function addLink(){
    let newLink = {
      source:sourceNode.id,
      target:targetNode.id,
      lineWidth:3
    }
    layer.closeAll('page');
    layer.open({
      id: 'addLink-1',
      title:'新增节点关系',
      type:1,
      shade:0,
      area:['350px','200px'],
      content:$('#addLink').html(),
      success:function(layero,index){
        form.on('submit(formAddLink)', function(data){
          layer.close(index)
          let param = data.field
          // visgraph.activeAddNodeLinks([],[newLink])
          newLink.label = param.relation
          let currentData = visgraph.getGraphData()
          let links = currentData.links
          let delLink = links[links.length-1]
          visgraph.deleteLink(delLink)
          let result = addRelation(sourceNode.id,targetNode.id,param.relation)
          if(result){
            newLink.id = result
            visgraph.addEdge(newLink)
          }else{
            notice.error("新增关系失败");
          }
          return false;
        });
      },
      cancel: function(){
        //右上角关闭回调
        let currentData = visgraph.getGraphData()
        let links = currentData.links
        let delLink = links[links.length-1]
        visgraph.deleteLink(delLink)
        // return
      }
    })
  }
  // 删除线条关系
  function beforeDelLink(_graphvis,type){
    let link = _graphvis.currentLink
    layer.confirm(`确定删除${link.label}?`,{title:'提示'},
      function(index){
        delRelation(link.id)
        _graphvis.rightMenuOprate(type)
        layer.close(index)
    })
  }

  //新增子节点
  function addNode(node){
    let result = addChildNode(node.properties),thisLayer
    if(!result){
      notice.warning(`节点【${node.label}】<br/>不可新增子节点！`,'提示');
    }else{
      layer.closeAll('page');
      layer.open({
		    id: 'addNode-1',
        title:'新增节点',
		    type:1,
		    shade:0,
        area:['500px','600px'],
		    content:$('#addNode').html(),
		    success:function(layero,index){
          thisLayer = index
          let option = addItems[0].option
          for(var i=0; i<option.length; i++){
            $("#relation").append(new Option(option[i].label, option[i].value))
            if(!i){
              changeSelect('relation',option[i].value)
              let opt = addItems[1].option
              addFormItem('select','label',opt)
              changeSelect('label',opt[0].value)
              if(addItems.length>2){
                addItems.slice(2).forEach(d=>{
                  addFormItem('text','form-body',d)
                })
              }
              //  添加按钮
            }
          }
          // 最关键需要重新渲染下拉框
          form.render('select')
          selectListener()
		    }
		});
    }
    form.on('submit(formAdd)', function(data){
      if(node.type == needCountryType){
        let country = getSubmarineCountry(node.properties)
        if(data.field.country != country){
          layer.confirm(`填写国家与既定国家不符，是否强制输入?`,{title:'提示'},
            function(index){
              addApi(node,data,thisLayer)
              layer.close(index)
          })
        }else{
          addApi(node,data,thisLayer)
        }
      }else{
        addApi(node,data,thisLayer)
      }
      return false;
    });
  }
  //  调用新增方法
  function addApi(node,data,thisLayer){
    let result = postAddNode(node.properties,data.field)
    layer.close(thisLayer)
    if(result){
      let nodeData = {
        ...data.field,
        id: result
      }
      addOneNode(node,nodeData)
      visgraph.addEdge({
        source:node.id,
        target:nodeData.id,
        label:nodeData.relation,
        lineWidth:3
      })
    }else{
      notice.error("新增子节点失败");
    }
  }
  //  修改子节点
  function updateNode(node){
    beforeUpdateNode(node)
    layer.open({
      id: 'updateNode-1',
      title:'修改节点',
      type:1,
      shade:0,
      area:['500px','600px'],
      content:$('#updateNode').html(),
      success:function(layero,index){
        updateItems.forEach(d=>{
          addFormItem('text','update-form-body',d)
        })
        form.on('submit(formUpdate)', function(data){
          let result = postUpdateNode(node,data.field)
          layer.close(index)

          if(result){
            visgraph.updateNodeLabel(node.id,data.field.name)
          }else{
            notice.error("更新节点失败");
          }
          return false;
        });
      }
    })
  }

  // 查看节点事件
  function showNodeEvent(node){
    layer.closeAll('page');
    if(node.type != 126){
      notice.warning('该节点无事件信息！','提示')
      return
    }
		layer.open({
      id: 'eventInfo-1',
      title:'事件信息',
      type:1,
      shade:0,
      area:['1000px','600px'],
      content:$('#nodeEventTeml').html(),
      success:function(layero,index){
        currentNode = node
        changePage(index,1,10,true)
      },
      cancel:function(){
        return
      }
		});
  }

  //  摘除切换页码后需要用的地方
  function changePage(index,pageNum,pageSize,init){
    let result = getEventData(currentNode.properties,pageNum,pageSize)
    if(!result.total && index){
      notice.warning('该节点无事件信息！','提示')
      layer.close(index)
      return
    }
    if(init){
      resetNodeEventInfo(currentNode,result,true)
    }else{
      resetNodeEventInfo(currentNode,result,false)
    }
  }

  // 监听select
  function selectListener(){
    //监听select
    layui.use('form', function () {
      form.on('select(relation)', function (data) {
          changeSelect('relation',data.value)
      });
      form.on('select(label)', function (data) {
        changeSelect('label',data.value)
    });
      form.render('select'); //刷新select选择框渲染
    })
  }

  // 添加formitem元素
  function addFormItem(type,id,data){
    if(type == 'select'){
      for(var i=0; i<data.length; i++){
        $(`#${id}`).append(new Option(data[i].label, data[i].value))
      }
      form.render('select')
    }else if(type =='text'){
      let taskNameList =
        '<div class="layui-form-item">' +
        '<label class="layui-form-label">'+ data.header +'</label>' +
        '<div class="layui-input-block">' +
        '<input type="text" οnkeyup="verify(this)" id="' + data.field + '" value="'+ data.value+'"  name="'+ data.field +'" lay-verify="required"  autocomplete="off" placeholder="" class="layui-input">' +
        '</div>' +
        '</div>'
      $(`#${id}`).append(taskNameList);
      form.render();
    }
  }

  // 删除节点
  function deleteNode(_graphvis,type){
    let node = _graphvis.currentNode
    layer.closeAll('page');
    layer.confirm(`确定删除${node.label}?`,{title:'提示'},
    function(index){
      delNodes(node.id)
      _graphvis.rightMenuOprate(type)
      layer.close(index)
    })
  }

  // 展示质量数
  function showQualityData(result){
    layer.closeAll();
    layer.open({
      id: 'quality',
      title:'质量覆盖率',
      type:1,
      shade:0,
      offset:'100px',
      area:['400px','300px'],
      content:'<div id="quality-rate"></div>',
      success:function(layero,index){
        $('#quality-rate').html(`本图谱的质量覆盖率为<span class="quality-font"> ${result} </span>`)
      }
    })
  }

	//节点自定义设置弹框
	function openNodeConfig(node){
		admin.popupRight({
		    id: 'nodeinfo-2',
        title:'节点配置',
		    type:1,
		    shade:0,
        area:['320px','100%'],
		    content:selectNodeSetTeml.innerHTML,
		    success:function(layero,index){
          var nodeInfo = {
            nodeId:node.id,
            nodeLabel:node.label,
            nodeShape:node.shape,
            nodeBgColor:'rgb('+node.fillColor+')',
            nodeSize:node.width,
            nodeLabelColor:'rgb('+node.fontColor+')',
            nodeLabelBgColor:node.labelBackGround?'rgb('+node.labelBackGround+')':"",
            nodeLabelPos:node.textPosition,
            nodeFont:node.font,
            nodeTextOffset:node.textOffsetY,
            borderWidth:node.borderWidth,
            borderColor:node.borderColor?'rgb('+node.borderColor+')':"",
            lineDash:(node.lineDash.lenght==2?'yes':'no')
          };
				form.val('selnode-config-form',nodeInfo);
				renderColorPicker('node-bgcolor','node-bgcolor-input',nodeInfo.nodeBgColor);
				renderColorPicker('node-bdcolor','node-bdcolor-input',nodeInfo.borderColor);
				renderColorPicker('node-labelcolor','node-labelcolor-input',nodeInfo.nodeLabelColor);
				renderColorPicker('node-labelbgcolor','node-labelbgcolor-input',nodeInfo.nodeLabelBgColor);
		    }
		});
	};

	//重新设置选中节点的样式
	function resetSelectNodeStyle(formVals){
		var node = visgraph.findNodeByAttr('id',formVals.nodeId);
		if(node){
			node.label = formVals.nodeLabel;
			node.width=node.height=formVals.nodeSize;
			node.shape = formVals.nodeShape;
			node.fillColor = getColorRgb(formVals.nodeBgColor);
			node.textPosition = formVals.nodeLabelPos;
			node.fontColor = getColorRgb(formVals.nodeLabelColor);
			node.labelBackGround = getColorRgb(formVals.nodeLabelBgColor);
			node.font = formVals.nodeFont;
			node.textOffsetY = Number(formVals.nodeTextOffset) || 2;
			node.borderWidth = Number(formVals.borderWidth) || 2;
			node.borderColor = getColorRgb(formVals.borderColor);
			node.lineDash = (formVals.lineDash=='yes'?[8,5]:[0]);
			visgraph.refresh();
		}
	};

	//设置选定连线的样式
	function openLinkConfig(link){
		admin.popupRight({
      id: 'lineStyle-config',
			title:'连线样式设置',
      type:1,
      shade:0,
      area:['320px','100%'],
      content:selectLinkSetTeml.innerHTML,
      success:function(layero,index){
        // console.log(link.lineDash);
        var linkInfo = {
          lineId:link._id,
          lineLabel:link.label,
          lineType:link.lineType,
          lineFont:link.font,
          lineColor:'rgb('+link.strokeColor+')',
          showArrow:(link.showArrow?'yes':'no'),
          background:link.background?'rgb('+link.background+')':'',
          lineLabelColor:'rgb('+link.fontColor+')',
          labelBackGround:link.labelBackGround?'rgb('+link.labelBackGround+')':'',
          lineDash:(link.lineDash.length==2?'yes':'no')
        };
        form.val('sellink-config-form',linkInfo);
        renderColorPicker('line-color','line-color-input',linkInfo.lineColor);
        renderColorPicker('line-labelcolor','line-labelcolor-input',linkInfo.lineLabelColor);
        renderColorPicker('line-labelbgcolor','line-labelbgcolor-input',linkInfo.lineColor);
        renderColorPicker('line-bgcolor','line-bgcolor-input',linkInfo.background);
      }
    });
	};

	//重新设置连线
	function resetSelectLinkStyle(formVals){
		var line = visgraph.currentLink;
		if(line){
			line.lineType=formVals.lineType;
			line.lineWidth=Number(formVals.lineWidth) || 2;
			line.strokeColor=getColorRgb(formVals.lineColor);
			line.fontColor = getColorRgb(formVals.lineLabelColor);
			line.labelBackGround = getColorRgb(formVals.lineLabelBgColor);
			line.colorType='defined';
			line.label = formVals.lineLabel;
			line.font = formVals.lineFont;
			line.showArrow = (formVals.showArrow=='yes'?true:false);
			line.lineDash = (formVals.lineDash=='yes'?[3,5]:[0]);
			line.background=getColorRgb(formVals.background);

			visgraph.refresh();
		}
	};

	//全局设置事件实现
	function globleReset(){
    layer.closeAll('page');
		admin.popupRight({
		    id: 'globle-reset-panel',
			title:'图显示设置',
		    type:1,
		    area:['350px', '100%'],
		    shade:0,
		    content:$('#globleSetTeml').html(),
		    success:function(layero,index){
		        form.render();

				var nodeConfig = admin.getTempData("nodeConfig")||{};
				form.val('node-config-form',nodeConfig);

				var lineConfig = admin.getTempData("lineConfig")||{};
				form.val('line-config-form',lineConfig);

				renderColorPicker('node-bgcolor','node-bgcolor-input',nodeConfig.nodeBgColor);
				renderColorPicker('node-labelcolor','node-labelcolor-input',nodeConfig.nodeLabelColor);
				renderColorPicker('node-labelbgcolor','node-labelbgcolor-input',nodeConfig.nodeLabelBgColor);

				renderColorPicker('line-color','linecolor-input',lineConfig.lineColor);
				renderColorPicker('line-labelcolor','line-labelcolor-input',lineConfig.lineLabelColor);
				renderColorPicker('line-labelbgcolor','line-labelbgcolor-input',lineConfig.lineLabelBgColor);
		    }
		});
	};

	//渲染颜色选择器
	function renderColorPicker(eleId,picInputId,defaultColor){
		colorpicker.render({
		    elem: '#'+eleId,
			color: defaultColor || 'rgb(68,66,66)',
			format: 'rgb',
			done: function(color){
			  $('#'+picInputId).val(color);
			}
		});
	};

	// 组装布局算法参数设置器
	function buildLayoutParams(layoutType){
		var gdata={nodes:[],links:[]};
		var layout=new LayoutFactory(gdata).createLayout(layoutType);
		var configs = layout.getConfig();

		var html = '<div class="layui-form" lay-filter="layout-config-form">';
		    html += '<table class="layui-table" lay-size="sm" lay-skin="nob">';
		configs.forEach(function(config){
			html+='<tr>';
			for(var param in config){
				if(param == 'label'){
					html+='<td>'+config['label']+'</td>'
				}else{
					var paramValue =config[param];
					if(paramValue instanceof Array){
						html+='<td>';
						html += '<select name="'+param+'" class="small-selector param">';
						paramValue.forEach(function(option){
							html += '<option value="'+option['value']+'">'+option['label']+'</option>';
						});
						html+='</select></td>';
					}else{
						html+='<td><input class="layui-input" type="number" name="'+param+'" value="'+paramValue+'"></td>';
					}
				}
			}
			html+='</tr>';
		});
		html+='</table>';
		html+='<button page-event="startRunLayout" data-layout="'+layoutType+'" class="pear-btn pear-btn-primary layui-btn-fluid"><i class="layui-icon layui-icon-play"></i>开始布局</button>';
		html+='</div>';
		return html;
	};

	// 定义执行布局计算的函数
	let currentLayout=null,loopName=null;
	function runLayout(layoutType,layoutConfig,init=false){
		var _graph =visgraph.getVisibleData();
		currentLayout = new LayoutFactory(_graph).createLayout(layoutType);
		if(currentLayout){
			visgraph.hideAllLink();
			currentLayout.initAlgo();
	    	currentLayout.resetConfig(layoutConfig);

	    	function loop(){
	    		cancelAnimationFrame(loopName);
				var i=0;
        if(init){
          setTimeout(()=>{
            stopLayout();
          },100)
        }
				while(i++ < 10){
					currentLayout.runLayout();
				}
				visgraph.refresh();
	    		loopName = requestAnimationFrame(loop);
	    	};
	    	loopName = requestAnimationFrame(loop);
		}
	};

	//停止布局计算
	function stopLayout(){
		cancelAnimationFrame(loopName);
		visgraph.translateToCenter();
		visgraph.showAllLink();
	};

	//重设布局算法参数
	function resetLayoutConfig(config){
		if(currentLayout){
			currentLayout.resetConfig(config);
		}
	};

	//简单数据设置
	function simpleDataSetter(){
		let gridTable;
		admin.open({
      id: 'simple-data-panel',
      title:'简单关系对设置',
      type:0,
      shade:0,
			area:['1000px','600px'],
			btn:['绘制可视化图','取消'],
			btnAlign:'c',
			maxmin:true,
      content:'<div id="simple-data-table"></div>',
      success:function(layero,index){
				gridTable = $('#simple-data-table').handsontable({
			           minRows: 10,
			           minCols: 4,
			           minSpareRows: 1,
			           //minSpareCols: 1,
			           rowHeaders: true,
			           colHeaders: true,
			           colWidths: [250,250,150,150],
			           wordWrap: true,
			           copyable: true,
			           autoColumnSize: true,
			           manualColumnResize: true,
			           fixedColumnsLeft: 1,
			           contextMenu:false,
			           colHeaders: ['起始点', '目标点', '关系类型'],
			           data: [["装备", '具体装备1', '子类'],["装备", '具体装备2', '子类'],["装备", '具体装备3', '子类']]
					}).data('handsontable');
		    },
			btn1:function(index,layero){
				var tableData = gridTable.getData();

				var linkIdMap=new Map();
				var nodeMap=new Map();
				var nodes=[],links=[];

				for(var i=0;i<tableData.length;i++){
				    var rowData = tableData[i];
				    if(rowData[0] == null || rowData[1] == null){
				        break;
				    }
				    var source=rowData[0];
				    if(nodeMap.get(source) == null){
				        nodes.push({id:source,size:50});
				        nodeMap.set(source,1);
				    }
				    var target=rowData[1];
				    if(nodeMap.get(target) == null){
				        nodes.push({id:target,size:50});
				        nodeMap.set(target,1);
				    }

				    var linkId = source+'_'+target;
				    if(linkIdMap.get(linkId) == null){
				        links.push({
				            source:source,
				            target:target,
				            weight:rowData[2]||2,
				            label:rowData[3],
				        });
				        linkIdMap.set(linkId,1);
				    }
				}
				renderGraph({nodes:nodes,links:links});
				layer.close(index);
			}
		});
	};

  // 还原数据
  function resetDataSetter(){
    renderGraph(retrievalData)
  }

	//复杂点边关系数据设置
	function complexDataSetter(){
		let nodeTable,linkTable;
		const html = `<div class="layui-tab layui-tab-card">
					  <ul class="layui-tab-title">
						<li class="layui-this">实体设置</li>
						<li>关系设置</li>
					  </ul>
					  <div class="layui-tab-content">
						<div class="layui-tab-item layui-show">
							<div id="node-data-table"></div>
						</div>
						<div class="layui-tab-item">
							<div id="link-data-table"></div>
						</div>
					  </div>
					</div>`;

		admin.open({
		    id: 'complex-data-panel',
			title:'点边关系数据设置',
		    type:0,
		    shade:0,
			area:['1000px','600px'],
			btn:['绘制可视化图','取消'],
			btnAlign:'c',
			maxmin:true,
		    content:html,
		    success:function(layero,index){
				nodeTable = $('#node-data-table').handsontable({
			           minRows: 10,
			           minCols: 3,
			           minSpareRows: 1,
			           rowHeaders: true,
			           colHeaders: true,
			           colWidths: [250,250,250],
			           wordWrap: true,
			           copyable: true,
			           autoColumnSize: true,
			           manualColumnResize: true,
			           fixedColumnsLeft: 1,
			           contextMenu:false,
			           colHeaders: ['点ID','点标签','点类型'],
			           data: [['常规潜艇','常规潜艇','类型'],["装备",'装备','装备'],['潜艇','潜艇','潜艇']]
					}).data('handsontable');

				linkTable = $('#link-data-table').handsontable({
				        minRows: 10,
				        minCols: 4,
				        minSpareRows: 1,
				        rowHeaders: true,
				        colHeaders: true,
				        colWidths: [250,250,150],
				        wordWrap: true,
				        copyable: true,
				        autoColumnSize: true,
				        manualColumnResize: true,
				        fixedColumnsLeft: 1,
				        contextMenu:false,
				        colHeaders: ['起始点ID','目标点ID','权重','关系类型'],
				        data: [['装备','潜艇',1 ,'子类'],['潜艇','常规潜艇',1,'子类']]
				    }).data('handsontable');
		    },
			btn1:function(index,layero){
				var linkMap=new Map();
				var nodeMap=new Map();
				var nodes=[],links=[];

				var nodeTableData = nodeTable.getData();
				for(var i=0;i<nodeTableData.length;i++){
				    var rowData = nodeTableData[i];
				    if(rowData[0] == null || rowData[1] == null){
				        break;
				    }
				    var nodeId=rowData[0];
				    if(nodeMap.get(nodeId) == null){
				        nodes.push({id:nodeId,label:rowData[1],type:rowData[2]||'default',size:50});
				        nodeMap.set(nodeId,1);
				    }
				}

				var linkTableData = linkTable.getData();
				for(var i=0;i<linkTableData.length;i++){
				    var rowData = linkTableData[i];
				    if(rowData[0] == null || rowData[1] == null){
				        break;
				    }
				    var sourceId=rowData[0],targetId=rowData[1];
				    var linkId=sourceId+'-'+targetId;
				    if(linkMap.get(linkId) == null){
				        links.push({
				            source:sourceId,
				            target:targetId,
				            weight:rowData[2]||1,
				            label:rowData[3],
				        });
				        linkMap.set(linkId,1);
				    }
				}
				renderGraph({nodes:nodes,links:links});
				layer.close(index);
			}
		});
	};

	//JSON数据设置
	function jsonDataSetter(){
		var html =	`<textarea id="jsonData" class="layui-textarea" style="height:150px;" placeholder="输入JSON格式图数据"></textarea>
					<div id="json" style="height:300px;border:1px solid #c5c5c5;overflow:auto;"></div>`;
		admin.open({
		    id: 'json1-data-panel',
			title:'JSON数据设置',
		    type:0,
		    shade:0,
			area:['800px','600px'],
			btn:['绘制可视化图','格式化数据','取消'],
			btnAlign:'c',
			maxmin:true,
		    content:html,
		    success:function(layero,index){
				var localStorData = null;
				if(localStorData == null){
				    localStorData = JSON.stringify(retrievalData);
				}
				$('#jsonData').val(localStorData);
				$("#json").JSONView(localStorData);
		    },
			btn1:function(index,layero){
				try{
				    var jsonData = $.trim($('#jsonData').val());
				    var graphData = JSON.parse(jsonData);
				    $("#json").JSONView(graphData);
				    localStorage.setItem("graphData",jsonData);

				    renderGraph(graphData);
				    layer.close(index);
				}catch(e){
					notice.error("JSON数据格式错误！");
				    return false;
				}
			},
			btn2:function(index,layero){
				try{
				    var jsonData = $.trim($('#jsonData').val());
				    var graphData = JSON.parse(jsonData);
				    $("#json").JSONView(graphData);
				    return false;
				}catch(e){
					notice.error("JSON数据格式错误！");
				    return false;
				}
			}
		});
	};

  //  导入数据设置
  function importDataSetter(){
		admin.open({
      id: 'import-data-panel',
      title:'依据数据绘图',
      type:0,
      shade:0,
			area:['500px','400px'],
			btn:['绘制可视化图','取消'],
			btnAlign:'c',
			maxmin:true,
      content:$('#importDataTeml').html(),
      success:function(layero,index){
				layui.use('upload', function(){
          var upload = layui.upload;
          //执行实例
          var uploadInst = upload.render({
            elem: '#import-upload' //绑定元素
            ,url: '/upload/' //上传接口
            ,done: function(res){
              //上传完毕回调
              let data = res.value,links=[],nodes=[],nodeMap={},index=1;
              data.forEach(d => {
                if(!nodeMap[d[0]]){
                  nodes.push({
                    id:index,
                    label:d[0]
                  })
                  nodeMap[d[0]] = index++
                }
                if(!nodeMap[d[1]]){
                  nodes.push({
                    id:index,
                    label:d[0]
                  })
                  nodeMap[d[0]] = index++
                }
                links.push({
                  target:nodeMap[d[1]],
                  source:nodeMap[d[0]],
                  label:d[2],
                  id:nodeMap[d[1]]+''+nodeMap[d[0]]
                })
              })
              renderGraph({nodes,links},true)
            }
            ,error: function(){
              //请求异常回调
            }
          });
        });
		    },
			btn1:function(index,layero){
				var tableData = gridTable.getData();

				var linkIdMap=new Map();
				var nodeMap=new Map();
				var nodes=[],links=[];

				for(var i=0;i<tableData.length;i++){
				    var rowData = tableData[i];
				    if(rowData[0] == null || rowData[1] == null){
				        break;
				    }
				    var source=rowData[0];
				    if(nodeMap.get(source) == null){
				        nodes.push({id:source,size:50});
				        nodeMap.set(source,1);
				    }
				    var target=rowData[1];
				    if(nodeMap.get(target) == null){
				        nodes.push({id:target,size:50});
				        nodeMap.set(target,1);
				    }

				    var linkId = source+'_'+target;
				    if(linkIdMap.get(linkId) == null){
				        links.push({
				            source:source,
				            target:target,
				            weight:rowData[2]||2,
				            label:rowData[3],
				        });
				        linkIdMap.set(linkId,1);
				    }
				}
				renderGraph({nodes:nodes,links:links});
				layer.close(index);
			}
		});
  }

	//模拟从服务端接口请求图数据，批量绘图
	function queryDataFromService(){
		admin.open({
		    id: 'service-data-panel',
			title:'服务接口设置',
		    type:0,
		    shade:0,
			offset:['0'],
			area:['500px','180px'],
			btn:['查询数据','取消'],
			btnAlign:'c',
		    content:'<input type="text" class="layui-input" value="http://127.0.0.1/graph/query"/>',
		    success:function(layero,index){
		    },
			btn1:function(index,layero){
				/* $.ajax({
					type : "POST",
					contentType: "application/json;charset=UTF-8",
					url : "http://127.0.0.1/graph/query",
					data : JSON.stringify({id:123}),
					success : function(result) {
						console.log(result);
					},
					error : function(e){
						console.log(e);
					}
				}); */
				graphDataCache = loadRemoteData('data/miserables.json');//dolphins
				renderGraph(graphDataCache);
				layer.close(index);
			}
		});
	};

	//内置示例数据弹框
	function openDemoData(){
		admin.popupRight({
		    id: 'demo-data-panel',
			title:'内置示例数据',
		    type:0,
		    shade:0,
			area:['350px','100%'],
			btn:[],
		    content:'<div id="demo-data-table" lay-filter="demoTable"></div>',
		    success:function(layero,index){
				var demoDatas=[
					{id:'tree',type:'json',name:'标准树数据'},
					{id:'miserables',type:'json',name:'悲惨的世界图谱'},
					{id:'hongloumeng',type:'json',name:'红楼梦图谱'},
					{id:'sanguo',type:'json',name:'三国人物图谱'},
					{id:'group-demo',type:'json',name:'群组网络数据'}
				];
				var header=[[{field:'name',title:'示例数据名称',templet:function(d){return '<a href="javascript:;" lay-event="openDemo" class="bluefont">'+d.name+'</a>';}}]];
				createTable('demo-data-table',header,demoDatas,false);
				table.on('tool(demoTable)', function(obj){
					var data = obj.data;
					var layEvent = obj.event;
					if(layEvent === 'openDemo'){
						graphDataCache = loadRemoteData('data/'+data.id+'.json');
						renderGraph(graphDataCache);
					}
				});
		    }
		});
	};

	//设置数据，重新绘制可视化图
	function renderGraph(graphData,noOperate){
		// var nodeCount = graphData.nodes.length;
		// if(nodeCount > 200){
    //   // 是否显示label
		//    visgraph.config.node.label.show=true;
		//    visgraph.config.link.label.show=true;
		// }else{
		//    visgraph.config.node.label.show=true;
		//    visgraph.config.link.label.show=true;
		// }
    disabledOperation(noOperate)
		visgraph.drawData(graphData);
		visgraph.setZoom('auto');
    setTimeout(()=>{
      runLayout('fastFR',{'froce':0.95,'linkDistance':150,'linkStrength':0.09,'charge':-300,gravity:0.015},true);
    })
	};

	//打开过滤面板
	function filterSetter(){
    layer.closeAll('page');
		admin.popupRight({
      id: 'filter-setter-panel',
			title:'实体和关系过滤',
      type:1,
      shade:0,
			area:['350px','100%'],
			btn:[],
      content:'<div id="filter-panel"></div>',
      success:function(layero,index){
        GraphVisFilter.init('#filter-panel',visgraph);
        form.render();
      }
		});
	};

  //  打开高级搜索面板
  function highLevelSetter(){
    admin.open({
      id: 'high-level-panel',
      title:'高级检索',
        type:0,
      shade:0,
      area:['340px','260px'],
      offset:'lt',
      btn:[],
      content:highlevelPanel.innerHTML,
      success:function(layero,index){
       form.render();
      }
  });
  }
	//查询节点弹框
	function fineNodeDialog(){
		admin.open({
      id: 'search-node-panel',
			title:'查询节点',
      type:0,
      shade:0,
			area:['340px','260px'],
			offset:'rt',
			btn:[],
		    content:findNodeTempl.innerHTML,
		    success:function(layero,index){
			   form.render();
		    }
		});
	};

	//打开统计面板
	function graphStatistics(){
    layer.closeAll('page');
		admin.popupRight({
		    id: 'graph-statistic-panel',
			title:'图统计信息',
		    type:0,
		    shade:0,
      offset:'rt',
			area:['360px','100%'],
			btn:[],
		    content:'<div id="statistic-panel"></div>',
		    success:function(layero,index){
			   var statistic = visgraph.getGraphStatistic()||{};
			   var htmlStrs = ['<table class="layui-table">'];
			   htmlStrs.push('<tr><td>实体数</td><td>'+statistic['nodesCount']+'</td></tr>');
			   htmlStrs.push('<tr><td>关系数</td><td>'+statistic['linksCount']+'</td></tr>');
			   htmlStrs.push('<tr><td>图密度</td><td>'+statistic['density']+'</td></tr>');
			   htmlStrs.push('<tr><td>平均度</td><td>'+statistic['avgDegree']+'</td></tr>');
			   htmlStrs.push('<tr><td>平均加权度</td><td>'+statistic['avgWeightDegree']+'</td></tr>');
			   htmlStrs.push('</table>');

			   $('#statistic-panel').html(htmlStrs.join(' '));
		    }
		});
	};

	//查找指定节点的N层关系
	function findNodeConnectDialog(){
		admin.open({
		    id: 'graph-statistic-panel',
			title:'分析N层关系',
		    type:0,
		    shade:0,
			offset:'rt',
			area:['350px','260px'],
			btn:[],
		    content:findNlayerTempl.innerHTML,
		    success:function(layero,index){
		    }
		});
	};

	//查找两点间的所有连通路径
	function findAllPathDialog(){
		admin.open({
		    id: 'find-allpath-panel',
			title:'分析两点间的连通路径',
		    type:0,
		    shade:0,
			offset:'rt',
			area:['350px','320px'],
			btn:[],
		    content:findAllPathTempl.innerHTML,
		    success:function(layero,index){
				form.render();
		    }
		});
	};

	//查找两点间的最短路径
	function findShortPathDialog(){
		admin.open({
		    id: 'find-shortpath-panel',
			title:'分析两点间的最短路径',
		    type:0,
		    shade:0,
			offset:'rt',
			area:['350px','320px'],
			btn:[],
		    content:findShortPathTempl.innerHTML,
		    success:function(layero,index){
				form.render();
		    }
		});
	};

	//查找指定节点的环路
	function findNodeCyclePath(){
		var html = '<div class="layui-form">'+
					'<table class="layui-table" lay-size="sm" lay-skin="nob">'+
					'	<tr>'+
					'		<td>目标点</td>'+
					'		<td><input type="text" id="findCycleNode" placeholder="输入指定节点名称查找其环路" class="layui-input"></td>'+
					'	</tr>'+
					'</table>'+
					'<button id="findCyclePath" class="pear-btn pear-btn-primary layui-btn-fluid">查找环路</button>'+
				'</div>';
		admin.open({
      id: 'find-nodecycle-panel',
			title:'查找指定点的环路',
      type:0,
      shade:0,
			offset:'rt',
			area:['320px','220px'],
			btn:[],
		    content:html,
		    success:function(layero,index){
				$('#findCyclePath').on('click',function(){
					var nodeLabel = $.trim($('#findCycleNode').val());
					if(nodeLabel){
						var node = visgraph.nodes.filter((_node)=>{
							return _node.label == nodeLabel;
						})[0];
						var paths = visgraph.findNodeCyclePath(node);
            layer.close(index)
						if(paths==null || paths.length == 0){
							notice.warning("图中没有找到闭环路径！",'提示');
						}
					}
				});
		    }
		});
	};

	//社区划分算法设置窗口
	function snaAnalyzeDialog(){
    layer.closeAll('page');
		admin.popupRight({
		    id: 'sna-analyze-panel',
			title:'社区划分算法设置',
		    type:0,
		    shade:0,
			offset:'rt',
			area:['350px','100%'],
			btn:[],
		    content:snaAnalyzeTempl.innerHTML,
		    success:function(layero,index){
				form.render();
		    }
		});
	};

	//布局算法设定弹框
	function layoutSelectDialog(){
    layer.closeAll('page');
		var htmlContent = '<div><input type="text" id="layoutSelect" lay-filter="layoutSelect" placeholder="选择布局算法" class="layui-input"/></div>';
			htmlContent += '<div id="layoutParams"></div>';
      admin.popupRight({
		    id: 'layout-algo-panel',
        title:'图布局算法设置',
		    type:0,
		    shade:0,
        area:['330px','100%'],
        btn:[],
		    content:htmlContent,
		    success:function(layero,index){
				treeSelect.render({
					elem: '#layoutSelect',
					data: 'data/layoutTypes.json',
					type: 'get',
					placeholder: '请选择布局算法',
					search: false,
					style: {
						folder: {
							enable: false
						},
						line: {
							enable: true
						}
					},
					click: function(d){
						stopLayout();
						var currentNode = d.current;
						if(currentNode.level == 0){
							var firstType = currentNode.children[0].id;
							treeSelect.checkNode('layoutSelect',firstType);
							$('#layoutParams').html(buildLayoutParams(firstType));
							form.render();
						}else{
							var layoutType= currentNode.id;
							$('#layoutParams').html(buildLayoutParams(layoutType));
							form.render();
						}
					},
					success: function (d) {
						stopLayout();
						treeSelect.checkNode('layoutSelect','fastFR');
						$('#layoutParams').html(buildLayoutParams('fastFR'));
						form.render();
					}
				});
		    },
			end : function(){
				stopLayout();
			}
		});
	};

	//节点大小根据属性映射
	function nodeMapAttrDialog(){
		admin.open({
		    id: 'node-mapattr-panel',
			title:'节点大小按照属性映射大小',
		    type:0,
		    shade:0,
			offset:'rt',
			area:['320px','320px'],
			btn:[],
		    content:nodeWithAttrTempl.innerHTML,
		    success:function(layero,index){
				form.render();
		    }
		});
	};

	//边粗细根据属性映射
	function edgeMapAttrDialog(){
		admin.open({
		    id: 'node-mapattr-panel',
			title:'边按照权重映射宽度',
		    type:0,
		    shade:0,
			offset:'rt',
			area:['320px','260px'],
			btn:[],
		    content:edgeWithAttrTempl.innerHTML,
		    success:function(layero,index){
				form.render();
		    }
		});
	};

  //  质量分析数据
  function qualityAttrDialog(){
    admin.open({
      id: 'node-quality-panel',
      title:'质量分析',
      type:0,
      shade:0,
      offset:'rt',
      area:['320px','260px'],
      btn:[],
      content:qualityAttrTempl.innerHTML,
      success:function(layero,index){
        form.render();
      }
    });
  }
  function relationshipDialog(){
    admin.open({
      id: 'node-relation-panel',
      title:'关系推理',
      type:0,
      shade:0,
      offset:'rt',
      area:['400px','300px'],
      btn:[],
      content:relationAttrTempl.innerHTML,
      success:function(layero,index){
        form.render();
      }
    });
  }
	//执行社区划分算法
	function runClusterAlog(clusterType,effectType){
		visgraph.clearClusters();
		var graph = visgraph.getVisibleData();
		var cluster = new ClusterFactory(graph).createClutser(clusterType);
		if(cluster){
		  var clusters = cluster.applay();
		  if(effectType == 1){
		    visgraph.addClusterContainer(clusters);
		  }
		  visgraph.refresh();
		}
	};

	//列表分析
	function tableAnalyze(){
		var templHtml = `<div class="layui-tab layui-tab-card" style="margin:10px;">
						 <ul class="layui-tab-title">
							<li class="layui-this">实体列表</li>
							<li>关系列表</li>
						 </ul>
						 <div class="layui-tab-content">
							<div class="layui-tab-item layui-show"><div id="nodes-table" lay-filter="nodeTable"></div></div>
							<div class="layui-tab-item"><div id="links-table"></div></div>
						 </div>
						</div>`;
		admin.open({
		    id: 'table-analyze-panel',
			title:'列表分析',
		    type:1,
			maxmin:true,
		    shade:0,
			area:['80%','80%'],
			btn:[],
		    content:templHtml,
		    success:function(layero,index){
				var graphData = visgraph.getVisibleData();
				var nodes = graphData.nodes.map((node)=>{
					return {
						id:node.id,
						label:node.label,
						type:node.type,
						degree:(node.inLinks||[]).length+(node.outLinks||[]).length,
						inDegree:(node.inLinks||[]).length,
						outDegree:(node.outLinks||[]).length
					}
				});
				var nodeTableHeader=[[{title:'ID',field:'id',templet:function(d){return '<a href="javascript:;" lay-event="findNode" style="color:#01AAED;">'+d.id+'</a>'}},{title:'标签',field:'label'},{title:'类型',field:'type',width:150},{title:'度',field:'degree',width:100,sort:true},{title:'入度',field:'inDegree',width:100,sort:true},{title:'出度',field:'outDegree',width:100,sort:true}]];
				createTable('nodes-table',nodeTableHeader,nodes,true);

				table.on('tool(nodeTable)', function(obj){
					var node = obj.data;
					var layEvent = obj.event;
					if(layEvent === 'findNode'){
						let node = visgraph.findNodeById(node.id);
					}
				});

				var links = graphData.links.map((link)=>{
					return {
						sourceId:link.source.id,
						source:link.source.label,
						targetId:link.target.id,
						target:link.target.label,
						type:link.type||link.label||'--',
						weight:link.weight
					}
				});
				var linkTableHeader=[[{title:'起始点',field:'source'},{title:'目标点',field:'target'},{title:'关系类型',field:'type',width:150},{title:'权重',field:'weight',width:100,sort:true}]];
				createTable('links-table',linkTableHeader,links,true);
		    }
		});
	};

	//创建指定表格
	function createTable(eleId,cols,data,pageAble,limit=20){
		table.render({
			elem: '#'+eleId,
			page: pageAble,
			limit,
			limits:[20,50,100],
			size:'sm',
			cols:cols,
			data:data
		});
	};

  // 创建指定页码
  function creatPage(ele,total,pageSize){
    laypage.render({
      elem: ele, //注意，这里的 page 是 ID，不用加 # 号
      count: total, //数据总数，从服务端得到
      limit: pageSize, // 每页条数
      limits: [10, 20, 30, 40, 50],
      layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],
      jump: function (obj, first) {
        //console.log(obj)
        //obj包含了当前分页的所有参数，比如：
        //console.log(obj.curr); //得到当前页，以便向服务端请求对应页的数据。
        //console.log(obj.limit); //得到每页显示的条数
        //首次不执行
        if(lastSize != obj.limit){
          lastSize = obj.limit
          changePage(null,1, obj.limit,true)
          return
        }
        if (!first) {
          changePage(null,obj.curr, obj.limit,false) // 分页点击传参
        }
      }
    });
  }
	//重新设置节点样式
	function resetNodeStyle(nodeConfig){
		visgraph.nodes.forEach(function(_node,i){
			_node.shape=nodeConfig.nodeShape;
			_node.fillColor=getColorRgb(nodeConfig.nodeBgColor);
			_node.textPosition=nodeConfig.nodeLabelPos;
			_node.textOffsetY=Number(nodeConfig.nodeTextOffset);
			_node.width = _node.height = Number(nodeConfig.nodeSize);
			_node.fontColor = getColorRgb(nodeConfig.nodeLabelColor);
			_node.labelBackGround = getColorRgb(nodeConfig.nodeLabelBgColor);
			_node.font = nodeConfig.nodeLabelBold+' '+nodeConfig.nodeLabelSize+'px '+nodeConfig.nodeLabelStyle;
			_node.showlabel = (nodeConfig.showlabel=='yes'?true:false);
		});
		visgraph.refresh();
	};

	//重新设置连线样式
	function resetLineStyle(lineConfig){
		visgraph.links.forEach(function(line,i){
			line.lineType=lineConfig.lineType;
			line.lineWidth=lineConfig.lineWidth;
			line.colorType=lineConfig.colorType;
			line.strokeColor=getColorRgb(lineConfig.lineColor);
			line.fontColor = getColorRgb(lineConfig.lineLabelColor);
			line.labelBackGround = getColorRgb(lineConfig.lineLabelBgColor);
			line.font = lineConfig.lineLabelBold+' '+lineConfig.lineLabelSize+'px '+lineConfig.lineLabelStyle;
			line.showArrow = (lineConfig.showArrow=='yes'?true:false);
			line.showlabel = (lineConfig.showlabel=='yes'?true:false);
		});
		visgraph.refresh();
	};

	//转换rgb颜色值
	function getColorRgb(color) {
		if (color && color.length > 0) {
			color = color.replace('rgb(', '').replace(')', '');
		} else {
			color = null;
		}
		return color;
	};

	//设置界面的一些样式和默认事件
	function bindDefaultEevent(){
		//工具栏功能切换事件
		$('#toolbar-nav ul > li.l1').click(function(){
			$(this).addClass('active').siblings('li.l1').removeClass('active');
		});

		//画布背景色选择器初始化
		colorpicker.render({
			elem: '#bgColorSelector',
			color: 'rgba(255,255,255,1)',
			format: 'rgb',
			predefine: true,
			alpha: true,
			done: function(color){
				color || this.change(color);
		    },
		    change: function(color){
				$('#graph-panel').css('background-color', color);
		    }
		});

		colorpicker.render({
			elem: '#fontColorSelector',
			color: 'rgb(10,10,10)',
			format: 'rgb',
			predefine: false,
			alpha: false,
			done: function(color){
				var rgbValue = getColorRgb(color);
				visgraph.nodes.forEach(function(n) {
					n.fontColor = rgbValue;
				});
				visgraph.refresh();
		    }
		});
	};

	//加载远程图格式数据文件,也可以是服务端接口返回数据
	function loadRemoteData(url){
		$.ajaxSettings.async = false;
		var data = null;

		$.get(url, function(result) {
			data = result;
		});

		$.ajaxSettings.async = true;
		return data;
	};

	//注册界面所有点击事件
	admin.pageEvents={
		quikOpt : function(e){
			var optType = $(this).data('opt');
			visgraph.setZoom(optType);
		},
		saveImage:function(){
			var imgtype = $(this).data('imgtype');
			visgraph.saveImage(5000,5000,imgtype);
		},
		mouseMode:function(){
			var mode = $(this).data('mode');
			visgraph.setMouseModel(mode);
		},
		codipos:function(){
			var mode = $(this).data('mode');
			if(mode == 'clockwise'){
				visgraph.rotateGraph(5);
			}else if(mode == 'aclockwise'){
				visgraph.rotateGraph(-5);
			}else{
				visgraph.translateOrZoom(mode,100);
			}
		},
		overview:function(){
			var show = $(this).data('show');
			var showFlag = (show==='no'?false:true);
			visgraph.showOverView(showFlag);
		},
		showLabel:function(){
			var show = $(this).data('show');
			var showFlag = (show==='no'?false:true);
			visgraph.showNodeLabel(showFlag);
			visgraph.showLinkLabel(showFlag);
		},
		globleSet:function(){
			globleReset();
		},
		saveNodeConfig:function(){
			var nodeConfig = form.val('node-config-form');
			admin.putTempData("nodeConfig",nodeConfig);
			resetNodeStyle(nodeConfig);
		},
		saveLineConfig:function(){
			var lineConfig = form.val('line-config-form');
			admin.putTempData("lineConfig",lineConfig);
			resetLineStyle(lineConfig);
		},
		dataSet:function(){
			var filetype = $(this).data('filetype');
			if(filetype == 'simple'){
				simpleDataSetter();
			}else if(filetype == 'complex'){
				complexDataSetter();
			}else if(filetype == 'json'){
				jsonDataSetter();
			}else if(filetype == 'interface'){
				queryDataFromService();
			}else if(filetype == 'demodata'){
        openDemoData();
      }else if(filetype == 'resetdata'){
				resetDataSetter()
			}else if(filetype == 'importdata'){
        debugger;
        // 导入数据后绘制图谱
        importDataSetter()
      }
		},
		viewopt:function(){
			var mode = $(this).data('mode');
      switch(mode){
        case 'clearAll':
          layer.confirm(`清空数据后所有数据将不显示，确定清空数据?`,{title:'提示'},
            function(index){
              visgraph.rightMenuOprate(mode);
              layer.close(index)
          })
          break;
        case 'showSelNode':
          layer.msg(`此操作只显示选中节点！`,{
            title:'提示',
            offset:'lt',
            icon:'layui-icon-tips'
          })
          visgraph.rightMenuOprate(mode);
          break;
        case 'hideSelNode':
          layer.msg(`此操作将隐藏选中节点！`,{
            title:'提示',
            offset:'lt',
            icon:'layui-icon-tips'
          })
          visgraph.rightMenuOprate(mode);
          break;
        default:
          visgraph.rightMenuOprate(mode);
          break;
      }
		},
		layoutSet:layoutSelectDialog,
		startRunLayout:function(){
			if($(this).find('.ew-btn-loading').length > 0){
				admin.btnLoading($(this)[0],'开始布局',false);
				$(this).removeClass('pear-btn-success').addClass('pear-btn-primary');
				stopLayout();
			}else{
				admin.btnLoading($(this)[0],'正在计算布局',true);
				$(this).removeClass('pear-btn-primary').addClass('pear-btn-success');

				var layoutConfig = form.val('layout-config-form');
				var layoutType = $(this).data('layout');
				runLayout(layoutType,layoutConfig);
			}
		},
		filterPanel:filterSetter,
    highlevelSearch:highLevelSetter,
		searchNode:fineNodeDialog,
		graphStatistics:graphStatistics,
		analyzeMode:function(){
			var mode = $(this).data('mode');
			if(mode == 'table'){
				tableAnalyze();
			}else if(mode == 'connect'){
				findNodeConnectDialog();
			}else if(mode == 'allpath'){
				findAllPathDialog();
			}else if(mode == 'shortpath'){
				findShortPathDialog();
			}else if(mode == 'cluster'){
				visgraph.findClusters();
			}else if(mode == 'checkCycle'){
				findNodeCyclePath();
			}else if(mode == 'nodeMapAttr'){
				nodeMapAttrDialog();
			}else if(mode == 'edgeMapAttr'){
				edgeMapAttrDialog();
			}else if(mode == 'quality'){
        qualityAttrDialog()
      }else if(mode == 'relationship'){
        relationshipDialog()
      }
		},
		snaAnlayze:snaAnalyzeDialog,
		findNodeConnect:function(){
			var formVals = form.val('find-connect-form');
			var nodeLabel = formVals.nodeLabel;
			var nLayerNum = parseInt(formVals.nlayerNo);
			visgraph.nLayerRelates(nodeLabel,nLayerNum);
		},
		findAllPath:function(){
			var formVals = form.val('find-allpath-form');
			var direction = formVals.direction;
			var startNode = formVals.startNode;
			var endNode = formVals.endNode;
			visgraph.pathAnalyze(startNode,endNode,direction);
		},
		findShortPath:function(){
			var formVals = form.val('find-shortpath-form');
			var direction = formVals.direction;
			var startNode = formVals.startNode;
			var endNode = formVals.endNode;
			visgraph.findShortPath(startNode,endNode,direction);
		},
		snaAnalyze:function(){
			var formVals = form.val('sna-analyze-form');
			var clusterType = formVals.clusterType;
			var effectType = formVals.effectType;
			runClusterAlog(clusterType,effectType);
		},
		confirmMapNodeSize:function(){
			var formVals = form.val('nodesize-mapattr-form');
			var nodeAttr = formVals.nodeAttr;
			var samllSize = Number(formVals.samllSize) || 10;
			var bigSize = Number(formVals.bigSize) || 120;

			visgraph.nodeMapSizeByDegree(nodeAttr,[samllSize,bigSize]);
		},
		confirmMapEdgeWidth:function(){
			var formVals = form.val('edge-mapattr-form');
			var samllSize = Number(formVals.samllSize) || 2;
			var bigSize = Number(formVals.bigSize) || 10;
			visgraph.applyLinkWeight([samllSize,bigSize]);
		},
    confirmQuality:function(){
      let formVals = form.val('quality-attr-form');
      let result = getQualityRate(formVals.url)
      showQualityData(result)
    },
    confirmRelation:function(){
      let formVals = form.val('relation-attr-form');
      //  获取数据  重绘
      let result = getYeSuRelation(formVals)
      renderGraph(result,true)
    },
		saveCurNodeConfig:function(){
			var formVals = form.val('selnode-config-form');
			resetSelectNodeStyle(formVals);
		},
		saveCurLineConfig:function(){
			var formVals = form.val('sellink-config-form');
      let link = visgraph.currentLink
      if(formVals.lineLabel != link.label){
        //  如果label 发生了改变 要修改这个线条的名称
        updateRelation(link.source.id,link.target.id,link.id,formVals.lineLabel)
      }
			resetSelectLinkStyle(formVals);
		},
		findNode:function(){
			var formVals = form.val('find-node-form');
			var attribute = formVals.attribute;
			var attrValue = $.trim(formVals.attrValue);
			if(attrValue.length > 0){
				var node = visgraph.findNodeByAttr(attribute,attrValue);
				if(node){
					visgraph.findNodeById(node.id);
				}else{
          layer.closeAll();
          notice.warning(`没有查询到节点【${attrValue}】！`,'提示');
        }
			}
		},
    highSearch:function(){
      var formVals = form.val('high-level-form');
			var attribute = formVals.attribute;
			var attrValue = $.trim(formVals.attrValue);
			if(attrValue.length > 0){
        //  成功之后要调取高级检索的节点和线条
        let data = searchNode(attrValue)
        renderGraph(data);
			}
    }
	};

	//添加一个节点到界面上
	function addOneNode(oldN,nodeInfo) {
		var _node = {};
		//_node.image="images/default.png";//设置一个节点图片
		_node.id = nodeInfo.id; //节点ID
		_node.label = nodeInfo.name;//节点名称
		_node.x = oldN.x + 200;//节点x坐标
		_node.y = oldN.y;//节点y坐标
		_node.color='30,160,255';//节点颜色值
    _node.properties=nodeInfo
		var node =visgraph.addNode(_node); //添加节点

		return node;
	};

	//模拟从服务端查询数据，此处示例从本地缓存数据中查找关联关系数据
	function searchData(cnode) {
    graphDataCache = spreadNode(cnode.id)
		if(graphDataCache == null){
			return {nodes:[],links:[]};
		}
    var relateLinks = graphDataCache.links.filter(function(l) {
      return l.source == cnode.id || l.target == cnode.id;
    });
    if (relateLinks.length == 0) {
      return {nodes:[],links:[]};
    }

    var relateNodeIds = [];
    relateLinks.forEach(function(l, i) {
      if (relateNodeIds.indexOf(l.source) == -1) {
        relateNodeIds.push(l.source);
      }

      if (relateNodeIds.indexOf(l.target) == -1) {
        relateNodeIds.push(l.target);
      }
    });

    //缓存数据中的关联节点
    var allRelateNodes = graphDataCache.nodes.filter(function(n) {
      return relateNodeIds.indexOf(n.id) != -1;
    });
    //设置一些属性，一般都由服务端组织好传回来
    allRelateNodes.map(function(n) {
      this.getImage(n)
      n.scale = 1;//大小系数重置
      n.x = Math.round(Math.random() * 50);//随机x坐标
      n.y = Math.round(Math.random() * 50);//随机y坐标
      // n.type='人物';//示例类型
    });
    return {nodes:allRelateNodes,links:relateLinks};
	};


	/**
	* 节点双击事件的业务实现
	* 此处是根据给节点是否有子节点用来判断执行展开还是收缩方法
	* 具体业务可以根据自己的实际逻辑去判断
	* @param node 当前要展开的节点对象
	*/
	function dbClickNodeEvent(node,flag,noTip){
		if(!node){
			return false;
		}
		//判断节点如果还没有展开过，则执行展开，并增加展开标记
		if(!node.expendFlag || flag){
			//实际业务需要从后端获取关系数据
			//====此处addData数据替换成后端返回即可===
      if(typeof flag == 'boolean' && !flag){
        node.expendFlag=false;
        //节点收起方法
        visActivePlugin.contractChildNode(node);
        return
      }
			var addData = searchData(node);
			var addNodeCount = addData.nodes.length;
			// if(addNodeCount < 2){
			// 	notice.warning(`节点【${node.label}】<br/>没有查询到更多关系！`,'提示');
			// 	return false;
			// }
			/**
			 * 业务使用方可以自己定义何时展开，何时收起
			 * 此处用追加标记的方式判断是不是展开过
			 */
			//节点标记为【展开】
			node.expendFlag=true;

			//注:根据增量节点数量动态选择适合自己业务展示的布局类型
			//grid,fastFR,frDirect,fr,concentric
			var layoutType=null;//默认星型布局
			if(addNodeCount >= 100){
				layoutType='fastFR';//快速布局
			}else if(addNodeCount >= 15){
				layoutType='fr';//网络布局
			}else if(addNodeCount >= 5){
				layoutType='frDirect';//中心圆布局
			}
			//执行节点展开方法
      // VueThis.changeFromOp(node,true)
			visActivePlugin.expendChildNode(node,addData,layoutType);
			// visgraph.expanded(node);
		}else{
			//节点展开标记恢复为【未展开】
			node.expendFlag=false;
			//节点收起方法
      VueThis.changeFromOp(node,false)
			visActivePlugin.contractChildNode(node);
		}
	};

  function disabledOperation(noOperation){
    if(!noOperation){
      visgraph.config.node.ondblClick = function(event,node){
        event.cancelBubble = true
				dbClickNodeEvent(node);//双击展开及收缩
        // clearTimeout(timeout);
			};
      visgraph.config.rightMenu = {
        nodeMenu:NodeRightMenu,
        linkMenu:LinkRightMenu
      }
    }else{
      visgraph.config.node.ondblClick = function(){
        return
      } ;
      visgraph.config.rightMenu = {}
    }
  }
  //  递归撤回节点的办法
  function contractNodes(treeNodes){
    if(treeNodes.children && treeNodes.children.length){
      treeNodes.children.forEach( d => {
        contractNodes(d)
      })
      let node = visgraph.findNodeById(treeNodes.id);
      visActivePlugin.contractChildNode(node);
      visgraph.hideSelected()
    }
  }
  //  递归展开的方法
  function expandAllNodes(treeNodes){
    if(treeNodes.children && treeNodes.children.length){
      let node = visgraph.findNodeById(treeNodes.id);
      dbClickNodeEvent(node,true)
      visgraph.rightMenuOprate('allSelect');
      visgraph.rightMenuOprate('rebackSel');
      treeNodes.children.forEach( d => {
        expandAllNodes(d)
      })
    }
  }
  // 加载树状节点图
  function initVue(){
    new Vue({
      el: '#nodeTree',
      data: function() {
        return {
          props: {
            label: 'name',
            children: 'children',
            isLeaf: 'leaf'
          },
          treeData:[],
          treeCopyData:[]
        }
      },
      mounted() {
        this.getNodeTree() 
        VueThis = this
      },
      methods: {
        getNodeTree(){
          let _this =this
          $.ajax({
            type:'get',
            url:urls.getNodeTreeInitUrl,
            contentType: "application/json;charset=UTF-8",
            data:{},
            async:false,
            success: function(res){
              if(res.value){
                nodeTree = res.value.map(d=>{
                  d.title = d.name
                  if(!d.children) d.leaf=true
                  return d
                })
              }
              _this.treeData = nodeTree
              _this.treeCopyData = nodeTree
            }
          })
        },
        loadNode(node, resolve) {
          if(!node.id) {
            this.$nextTick(()=>{
              this.$refs.nodeTree.setCheckedKeys(this.treeData.map(d=>d.id))
            })
            return
          }
          let _this = this
          $.ajax({
            type:'post',
            url:urls.getNextnodeTreeUrl,
            contentType: "application/json;charset=UTF-8",
            data:JSON.stringify({id:node.data.id}),
            async:false,
            success: function(res){
              if(res.value){
                nodeTree = res.value.map(d=>{
                  d.title = d.name
                  return d
                })
                // node.children = nodeTree
                resolve(nodeTree)
                _this.currentId = node.data.id
                _this.initTreeCopyData(_this.treeCopyData,nodeTree)
                let checked = _this.$refs.nodeTree.getCheckedKeys()
                if(!checked.includes(node.data.id)){
                  checked.push(node.data.id)
                }
                _this.$refs.nodeTree.setCheckedKeys([...checked])
                visgraph.rightMenuOprate('allSelect');
                visgraph.rightMenuOprate('rebackSel');
                let curNode = visgraph.findNodeById(node.data.id)
                dbClickNodeEvent(curNode)
              }
              else{
                resolve([])
              }
            }
          })
        },
        changeCheck(data,nodeSelf){
          let node = visgraph.findNodeById(data.id);
          let flag = nodeSelf.checkedKeys.includes(data.id)
          this.currentId = data.id
          treeNodes = this.getTreeData(this.treeCopyData)
          if(flag){
            expandAllNodes(this.result)
          }else{
            contractNodes(this.result)
          }
          dbClickNodeEvent(node,flag,!flag)
          if(!flag){
            dataObj[data.id]
          }
        },
        getTreeData(data){
          let result = data.filter(d=>{
            return d.id == this.currentId
          })
          if(!result.length){
            data.forEach(d=>{
              if(d.children && d.children.length){
                this.getTreeData(d.children)
              }
            })
          }else{
            this.result = result[0]
            return result[0]
          }
        },
        initTreeCopyData(tree,data){
          let cur = -1
          let result = tree.filter((d,index)=>{
            if(d.id == this.currentId){
              cur = index
              return true
            }
            return false
          })
          if(!result.length){
            tree.forEach(d=>{
              if(d.children && d.children.length){
                this.initTreeCopyData(d.children,data)
              }
            })
          }else{
            tree[cur].children = data
          }
        },
        // this.$refs.nodeTree.setCheckedKeys(this.treeData.map(d=>d.id))
        changeFromOp(node,flag){
          this.$refs.nodeTree.setChecked(node.id,flag)
        }
      },
    })
  }
});
},false)

